ceph-模块初始化中 prefork源码解析
Last updated on 8 months ago
在 osd启动流程的代码中有一个 global_init_prefork() 的 函数,发现在很多 模块启动流程都有 这个函数,这和模块对应的进程有关系,所以对这个函数剖析下
具体实现函数都在 Preforker 类中
在先执行是 global_init_prefork(g_ceph_context) 函数
global_init_prefork(g_ceph_context)
prefork 的预初始化
1 |
|
pidfile_write(conf) 函数i就是把进程的 pid 写进 一个文件里,为什么这么做后面再说
forker.prefork
关键部分,这里主要做的是 fork一个子进程,接下来执行的操作都是由 子进程执行,父进程处于 wait状态,并且这里也对标准输入输出做了些处理
父进程处于等待状态,再执行 setsid 建立新会话
global_init_postfork_start();
该函数重新再把当前进程的pid重新写入到pid文件
为什么创建一个经常需要 建立一个pid文件? 可这里先从 pid 文件创建开始讲
在刚才的 pidfile_write 函数中,有调用了一个 函数 pidfh::open
pidfh::open 中调用了 open,创建 文件
随后 获取创建文件的信息保存 Preforker 类中
最后一步比较关键,用 flock 给文件上锁
这里确保 只有获取锁的进程才能读取文件,没有锁的话直接退出,而且只有一把锁,可以防止进程启动多个副本,只有获得pid文件(固定路径固定文件名)写入权限(F_WRLCK)的进程才能正常启动并把自身的PID写入该文件中。其它同一个程序的多余进程则自动退出。
假如说我开了两个终端,都同时创建 osd,而且编号都相同,为了确保一个osd对应一个守护进程,跟据程序的设定,必须要读取pid文件才能继续执行,那谁先获得了 pid文件的读写锁,谁就可以继续执行;而且pid文件保存的是 进程的pid,所以可以通过文件来判断进程是否存在